//
//  CCClippingSkeletalSprite.cpp
//  BattleEmpireTest
//
//  Created by droidhang on 13-7-2.
//
//

#include "CCClippingSkeletalSprite.h"
#include "CCSkeletonCache.h"

CCClippingSkeletalSprite::CCClippingSkeletalSprite() {
    _count=1;
}

CCClippingSkeletalSprite::~CCClippingSkeletalSprite() {
}

CCClippingSkeletalSprite* CCClippingSkeletalSprite::create(const char* key,CCClippingNode* clipper,const vector<bool>& bvt,CCSprite* sprtAntialias) {
    CCSkeleton* s=CCSkeletonCache::getInstance()->getSkeleton(key);
	return create(s,clipper,bvt,sprtAntialias);
}

CCClippingSkeletalSprite* CCClippingSkeletalSprite::create(CCSkeleton* s,CCClippingNode* clipper,const vector<bool>& bvt,CCSprite* sprtAntialias) {
    CCClippingSkeletalSprite* sprite = new CCClippingSkeletalSprite();
    if (sprite && sprite->init(clipper, bvt,sprtAntialias)) {
        sprite->setSkeleton(s);
        return (CCClippingSkeletalSprite*)sprite->autorelease();
    }
	CC_SAFE_DELETE(sprite);
    return NULL;
}

bool CCClippingSkeletalSprite::init(cocos2d::CCClippingNode *clipper, const vector<bool> &bvt,CCSprite* sprtAntialias) {
    
    if (!CCSkeletalSprite::init()) {
        return false;
    }
    
    _bvt=bvt;
    _iter=_bvt.begin();
    
    clipper->retain();
    _rootSpriteList.push_back(clipper);
    
    if (sprtAntialias) {
        CCNode* sten=clipper->getStencil();
        
        sprtAntialias->retain();
        sprtAntialias->setPosition(sten->getPosition());
        sprtAntialias->setAnchorPoint(sten->getAnchorPoint());
        sprtAntialias->setScaleX(sten->getScaleX());
        sprtAntialias->setScaleY(sten->getScaleY());
        
        _count=2;
        _rootSpriteList.push_back(sprtAntialias);
    }
    
    return true;
}

void CCClippingSkeletalSprite::createSprites(cocos2d::CCSprite *sprite,bool &lastAdditive,bool &nowAdditive) {
    if (_iter==_bvt.end() || *_iter==true) {
        //need clipping
        (*_rootSpriteList.begin())->addChild(sprite);
    }
    else {
        CCSpriteBatchNode* rootSprite=NULL;
        if (_rootSpriteList.size()==_count) {
            CCTexture2D* texture = sprite->getTexture();
            rootSprite=CCSpriteBatchNode::createWithTexture(texture);
            _rootSpriteList.push_back(rootSprite);
            rootSprite->retain();
            lastAdditive=nowAdditive;
            if (nowAdditive) {
                ccBlendFunc blendFunc;
                if (texture->hasPremultipliedAlpha()) {
                    blendFunc.src=GL_ONE;
                }
                else {
                    blendFunc.src=GL_SRC_COLOR;
                }
                blendFunc.dst=GL_ONE;
                rootSprite->setBlendFunc(blendFunc);
            }
        }
        else {
            rootSprite=(CCSpriteBatchNode*)*_rootSpriteList.rbegin();
            if (rootSprite->getTexture()->getName()!=sprite->getTexture()->getName() || lastAdditive!=nowAdditive) {
                CCTexture2D* texture = sprite->getTexture();
                rootSprite=CCSpriteBatchNode::createWithTexture(texture);
                _rootSpriteList.push_back(rootSprite);
                rootSprite->retain();
                if (nowAdditive) {
                    ccBlendFunc blendFunc;
                    if (texture->hasPremultipliedAlpha()) {
                        blendFunc.src=GL_ONE;
                    }
                    else {
                        blendFunc.src=GL_SRC_COLOR;
                    }
                    blendFunc.dst=GL_ONE;
                    rootSprite->setBlendFunc(blendFunc);
                }
                lastAdditive=nowAdditive;
            }
        }
        rootSprite->addChild(sprite);
    }
    _iter++;
}

void CCClippingSkeletalSprite::setShaderProgram(cocos2d::CCGLProgram *pShaderProgram) {
    auto it=_rootSpriteList.begin();
    CCObject* object;
    CCARRAY_FOREACH((*it)->getChildren(),object ) {
        CCNode* node=(CCNode*)object;
        node->setShaderProgram(pShaderProgram);
    }
    for (it++ ; it!=_rootSpriteList.end(); it++) {
        (*it)->setShaderProgram(pShaderProgram);
    }
}

void CCClippingSkeletalSprite::setScaleForSkeletalSprite(float scale) {
    auto it=_rootSpriteList.begin();
    if (_count==2) {
        it++;
    }
    for (it++ ; it!=_rootSpriteList.end(); it++) {
        (*it)->setScale(scale);
    }
}